
#include "ipfe_shape_pattern.h"

// [*] CShapePatternList

void CShapePatternList::Clear()
{
	wAmount = 0;
	xL_List.Clear();
	yL_List.Clear();
	xH_List.Clear();
	yH_List.Clear();
	Weight_List.Clear();

	PatternAmount = 0;
	pwlStart.Resize(1); pwlStart.pElement[0] = 0;
	//pwlAmount.Clear();
}

void CShapePatternList::PushBack_SingleWindow(const CRectBox<int>& Box, double Weight)
{
	++wAmount;
	xL_List.PushBack(Box.x - 1);
	yL_List.PushBack(Box.y - 1);
	xH_List.PushBack(Box.x - 1 + Box.w);
	yH_List.PushBack(Box.y - 1 + Box.h);
	Weight_List.PushBack(Weight);
}

void CShapePatternList::PushBack_PatternFinishSign()
{
	int t = wAmount - pwlStart.pElement[PatternAmount];
	if (t < 1) return;
	++PatternAmount;
	pwlStart.PushBack(wAmount);
	//pwlAmount.PushBack(t);
}

void CShapePatternList::InputFromStream(istream& inStream)
{
	int pbn;

	Clear();
	if (!(inStream>>pbn)) return;
	for ( ; pbn > 0; --pbn )
		PushBack_MultiScalePatternList_FromStream(inStream);
}

void CShapePatternList::PushBack_MultiScalePatternList_FromStream(istream& inStream)
{
	int i,j,o;

	int ns, np, nb;
	CSimpleTypeArray<double> ScaleList;
	CSimpleTypeArray<CRectBox<double>> pptBoxList;
	CSimpleTypeArray<double> bwList;
	CRectBox<double> pptBox;
	CRectBox<int> newBox;
	double lx, ly, ux, uy;
	double ts, tw;

	inStream>>ns; ScaleList.Resize(ns); for ( j = 0; j < ns; ++j ) inStream>>ScaleList.pElement[j];
	inStream>>np;
	for ( i = 0; i < np; ++i )
	{
		inStream>>nb;
		pptBoxList.Clear();
		bwList.Clear();
		for ( o = 0; o < nb; ++o )
		{
			inStream>>pptBox.x>>pptBox.y>>pptBox.w>>pptBox.h>>tw;
			pptBoxList.PushBack(pptBox);
			bwList.PushBack(tw);
		}
		for ( j = 0; j < ns; ++j )
		{
			ts = ScaleList.pElement[j];
			for ( o = 0; o < nb; ++o )
			{
				pptBox = pptBoxList.pElement[o];
				tw = bwList.pElement[o];

				lx = pptBox.x * ts;	ux = lx + pptBox.w * ts;
				ly = pptBox.y * ts;	uy = ly + pptBox.h * ts;

				newBox.x = CMyMath::TranslateNumber_Round(ceil(lx), 0);
				newBox.y = CMyMath::TranslateNumber_Round(ceil(ly), 0);
				newBox.w = CMyMath::TranslateNumber_Round(ceil(ux), 0) - newBox.x;
				newBox.h = CMyMath::TranslateNumber_Round(ceil(uy), 0) - newBox.y;

				PushBack_SingleWindow(newBox, tw);
			}
			PushBack_PatternFinishSign();
		}
	}
}

void CShapePatternList::OutputToStream(ostream& outStream) const
{
	int i,j,jn;
	CRectBox<int> tBox;
	int* pXL;
	int* pYL;
	int* pXH;
	int* pYH;
	double* pW;

	outStream<<"1"<<endl;
	outStream<<"1"<<endl;
	outStream<<"\t1.0"<<endl;
	outStream<<PatternAmount<<endl;
	for ( i = 0; i < PatternAmount; ++i )
	{
		jn = GetPattern(pXL, pYL, pXH, pYH, pW, i);
		outStream<<"\t"<<jn<<endl;
		outStream.precision(6);
		for ( j = 0; j < jn; ++j )
		{
			tBox.x = *pXL + 1;
			tBox.y = *pYL + 1;
			tBox.w = *pXH - *pXL;
			tBox.h = *pYH - *pYL;
			++pXL; ++pYL; ++pXH; ++pYH;
			outStream<<"\t"<<tBox.x;
			outStream<<"\t"<<tBox.y;
			outStream<<"\t"<<tBox.w;
			outStream<<"\t"<<tBox.h;
			outStream<<"\t"<<fixed<<*(pW++);
			outStream<<endl;
		}
	}
}

void CShapePatternList::LoadFromFile(string strFN_ShapePatternList)
{
	ifstream inFile(strFN_ShapePatternList.c_str());
	InputFromStream(inFile);
	inFile.clear();
	inFile.close();
}

void CShapePatternList::SaveToFile(string strFN_ShapePatternList) const
{
	ofstream outFile(strFN_ShapePatternList.c_str());
	OutputToStream(outFile);
	outFile.clear();
	outFile.close();
}

int CShapePatternList::GetPattern(int*& pXL, int*& pYL, int*& pXH, int*& pYH, double*& pW, int PatternIndex) const
{
	if (PatternIndex<0 || PatternIndex>=PatternAmount)
	{
		pXL = pYL = pXH = pYH = NULL;
		pW = NULL;
		return 0;
	}
	int i = pwlStart.pElement[PatternIndex];
	pXL = xL_List.pElement + i;
	pYL = yL_List.pElement + i;
	pXH = xH_List.pElement + i;
	pYH = yH_List.pElement + i;
	pW = Weight_List.pElement + i;
	return (pwlStart.pElement[PatternIndex + 1] - i);
}

void CShapePatternList::GenGridPattern(ostream& outStream,
	double xBase, double yBase,
	double W, double H,
	int wCell, int hCell,
	int wBlkCel, int hBlkCel)
{
	int ix, iy;
	outStream.precision(2);
	outStream<<(wCell-wBlkCel+1)*(hCell-hBlkCel+1)<<endl;
	for ( ix = 0; ix <= wCell - wBlkCel; ++ix ) for ( iy = 0; iy <= hCell - hBlkCel; ++iy )
	{
		outStream<<"\t"<<"1"<<endl;
		outStream<<"\t"<<fixed<<xBase+W/wCell*ix;
		outStream<<"\t"<<fixed<<yBase+H/hCell*iy;
		outStream<<"\t"<<wBlkCel;
		outStream<<"\t"<<hBlkCel;
		outStream<<"\t"<<"1.0"<<endl;
	}
}

void CShapePatternList::GenGridPattern(
	CShapePatternList& DstSPL, bool fAppendMode,
	double xCenter, double yCenter,
	int AmountX, int AmountY,
	double wCell, double hCell,
	double xStride, double yStride,
	double Weight)
{
	if (!fAppendMode)
		DstSPL.Clear();

	double xLow = xCenter - (xStride * (AmountX - 1) + wCell) * 0.5;
	double yLow = yCenter - (yStride * (AmountY - 1) + hCell) * 0.5;

	int ix, iy;
	CRectBox<double> fBox;
	CRectBox<int> iBox;

	fBox.w = wCell;
	fBox.h = hCell;
	for ( ix = 0; ix < AmountX; ++ix ) for ( iy = 0; iy < AmountY; ++iy )
	{
		fBox.x = xLow + xStride * ix;
		fBox.y = yLow + yStride * iy;
		iBox = fBox;
		DstSPL.PushBack_SingleWindow(iBox, Weight);
		DstSPL.PushBack_PatternFinishSign();
	}
}

void CShapePatternList::GenBlockPattern(
	CShapePatternList& DstSPL, bool fAppendMode,
	double xCenter, double yCenter,
	double wWindow, double hWindow,
	double wBlock, double hBlock,
	double xStride, double yStride,
	const CSimpleTypeArray<CShapePattern_SingleCellInBlock>& RatioCellList
	)
{
	if (!fAppendMode)
		DstSPL.Clear();

	int xAmount = CMyMath::TranslateNumber_Round((wWindow - wBlock) / xStride, (int)0) + 1;
	int yAmount = CMyMath::TranslateNumber_Round((hWindow - hBlock) / yStride, (int)0) + 1;

	double xLow = xCenter - (xStride * (xAmount - 1) + wBlock) * 0.5;
	double yLow = yCenter - (yStride * (yAmount - 1) + hBlock) * 0.5;

	int ix, iy, ic;
	CRectBox<double> fBox;
	CRectBox<int> iBox;

	for ( ix = 0; ix < xAmount; ++ix ) for ( iy = 0; iy < yAmount; ++iy )
	{
		for ( ic = 0; ic < (int)RatioCellList.Size; ++ic )
		{
			CShapePattern_SingleCellInBlock& iCell = RatioCellList.pElement[ic];
			fBox.x = iCell.RatioBox.x * wBlock + xLow + xStride * ix;
			fBox.y = iCell.RatioBox.y * hBlock + yLow + yStride * iy;
			fBox.w = iCell.RatioBox.w * wBlock;
			fBox.h = iCell.RatioBox.h * hBlock;
			iBox = fBox;
			DstSPL.PushBack_SingleWindow(iBox, iCell.Weight);
		}
		DstSPL.PushBack_PatternFinishSign();
	}
}

